using System;
using System.Linq;
using NUnit.Framework;

namespace 物料需求计划_在生产能力约束下的生产计划
{
    public class Tests
    {
        int[] requirements = new[]
        {
            100,
            79,
            230,
            105,
            3,
            10,
            99,
            126,
            40
        };


        int[] constraints = new[]
        {
            120,
            200,
            200,
            400,
            300,
            50,
            120,
            50,
            30
        };

        private int h = 2;
        private int k = 450;

        [SetUp]
        public void Setup()
        {
        }

        [Test]
        public void Test1()
        {
            // 本周需要额外生产的需求
            int[] extraRequirement = new int[requirements.Length];

            // 调整之后的本周需求
            int[] r1 = new int[requirements.Length];

            // 本周的剩余产能
            int[] productionRemain = new int[requirements.Length];

            // 优化后的计划产出量
            int[] y = new int[requirements.Length];

            for (int i = requirements.Length - 1; i >= 0; i--)
            {
                int extra = 0;

                if (i != requirements.Length - 1)
                {
                    int remain = requirements[i + 1] + extraRequirement[i + 1] - constraints[i + 1];

                    if (remain > 0)
                    {
                        extra = extraRequirement[i] = remain;
                    }
                }


                r1[i] = Math.Min(requirements[i] + extra, constraints[i]);

                // 当前周的剩余产能
                int currentProductRemain = constraints[i] - r1[i];

                y[i] = r1[i];
                
                if (currentProductRemain > 0)
                {
                    productionRemain[i] = currentProductRemain;

                    for (int j = i+1; j < y.Length; j++)
                    {
                        // 当前周的产能 > 未来周的产能
                        // 并且 在当前周生产以后，花费的库存成本低于开工成本
                        if (currentProductRemain> y[j] && y[j] * h * (j - i) < k)
                        {
                            y[i] += y[j];
                            currentProductRemain -= y[j];
                            y[j] = 0;
                        }
                    }
                    
                   
                }
                
            }


            CollectionAssert.AreEqual(new int[]
            {
                0,
                30,
                0,
                0,
                25,
                65,
                86,
                10,
                0
            }, extraRequirement);

            CollectionAssert.AreEqual(new int[]
            {
                100,
                109,
                200,
                105,
                28,
                50,
                120,
                50,
                30,
            }, r1);
            
            printLine(requirements, "r:\t");
            printLine(constraints, "c:\t");
            printLine(r1, "r1:\t");
            printLine(productionRemain, "re:\t");
            
            printLine(y, "y:\t");
          
            
            Assert.AreEqual(r1.Sum(),y.Sum());
        }

        private void printLine(int[] ints, string title)
        {
            Console.WriteLine(title + string.Join(",", ints.Select(num => string.Format("{0,-4}",num)).ToArray()));
        }
    }
}